module top(
	input clk,
	input rst,

	input joystick_miso,
	output joystick_clk,
    output joystick_mosi,
    output joystick_cs,

	output tx,

	output       tmds_clk_n,
	output       tmds_clk_p,
	output [2:0] tmds_d_n,
	output [2:0] tmds_d_p
);

localparam FREQ=27_000_000; 

//===========================
//reg [0:7] psout1_1 = {8'h53,8'h4c,8'h52,8'h53,8'h55,8'h52,8'h44,8'h4c};
//reg [0:7] psout2_1 = {8'h45,8'h33,8'h33,8'h54,8'h50,8'h49,8'h4e,8'h45};
//reg [7:0] psout1_2 = {8'h4c,8'h52,8'h4c,8'h52,8'h54,8'h43,8'h58,8'h53};
//reg [7:0] psout2_2 = {8'h32,8'h32,8'h31,8'h31,8'h49,8'h49,8'h58,8'h51};
//===========================
wire [7:0] joy_rx[0:5];
reg sclk;
localparam SCLK_DELAY = FREQ / 250_000 / 2;
reg [$clog2(SCLK_DELAY)-1:0] sclk_cnt;

//===========================
reg [7:0] wdata;
reg [7:0] status;
reg wvalid;
wire woready;
reg [7:0] spiout1;
reg [7:0] spiout2;
//===========================
reg [1:0] xypos;
reg [1:0] direct;
reg [8:0] axis_xpos;
reg [8:0] axis_ypos;
//===========================
always @(posedge clk) begin
    sclk_cnt <= sclk_cnt + 1;
    if (sclk_cnt == SCLK_DELAY-1) begin
        sclk = ~sclk;
        sclk_cnt <= 0;
    end
end

uart uart_inst(
    .clk        (clk),
    .rst        (rst),
    .wdata_i    (wdata),
    .wvalid_i   (wvalid),
    .wready_o   (woready),
    .tx_o       (tx)
);

dualshock_controller controller (
    .I_CLK250K(sclk),
	.I_RSTn(1'b1),
    .O_psCLK(joystick_clk),
	.O_psSEL(joystick_cs),
	.O_psTXD(joystick_mosi),
    .I_psRXD(joystick_miso),
    .O_RXD_1(joy_rx[0]),
	.O_RXD_2(joy_rx[1]),
	.O_RXD_3(joy_rx[2]),
    .O_RXD_4(joy_rx[3]),
	.O_RXD_5(joy_rx[4]),
	.O_RXD_6(joy_rx[5]),
    // config=1, mode=1(analog), mode_en=1
    .I_CONF_SW(1'b1),
	.I_MODE_SW(1'b1),
	.I_MODE_EN(1'b1),
    .I_VIB_SW(2'b00),
	.I_VIB_DAT(8'hff)     // no vibration
);

Gowin_rPLL u_pll (
  .clkin(clk),
  .clkout(clk_p5),
  .lock(pll_lock)
);

Gowin_CLKDIV u_div_5 (
    .clkout(clk_p),
    .hclkin(clk_p5),
    .resetn(pll_lock)
);

Reset_Sync u_Reset_Sync (
  .resetn(sys_resetn),
  .ext_reset(rst & pll_lock),
  .clk(clk_p)
);
 
svo_hdmi svo_hdmi_inst (
	.clk(clk_p),
	.resetn(sys_resetn),

	 //video clocks
	.clk_pixel(clk_p),
	.clk_5x_pixel(clk_p5),
	.locked(pll_lock),

	.xypos(xypos),
	.direct(direct),
	.axis_xpos(axis_xpos),
	.axis_ypos(axis_ypos),
	 //output signals
	.tmds_clk_n(tmds_clk_n),
	.tmds_clk_p(tmds_clk_p),
	.tmds_d_n(tmds_d_n),
	.tmds_d_p(tmds_d_p)
);

reg [2:0] psstatus;
always @(posedge clk or negedge rst) begin
	if (!rst) begin
		psstatus<=0;
		axis_xpos<=10;
		axis_ypos<=7;
	end
	else begin
		case (psstatus)
				0 : begin
					case (joy_rx[0])
						8'b1111_1110:begin spiout1=8'h53;spiout2=8'h45;end
						8'b1111_1101:begin spiout1=8'h4c;spiout2=8'h33;end
						8'b1111_1011:begin spiout1=8'h52;spiout2=8'h33;end
						8'b1111_0111:begin spiout1=8'h53;spiout2=8'h54;end
						8'b1110_1111:begin spiout1=8'h55;spiout2=8'h50;xypos<=2'b00;
											axis_xpos<=2;axis_ypos<=2;end
						8'b1101_1111:begin spiout1=8'h52;spiout2=8'h49;xypos<=2'b01;
											axis_xpos<=3;axis_ypos<=3;end
						8'b1011_1111:begin spiout1=8'h44;spiout2=8'h4E;xypos<=2'b10;
											axis_xpos<=4;axis_ypos<=4;end
						8'b0111_1111:begin spiout1=8'h4c;spiout2=8'h45;xypos<=2'b11;
											axis_xpos<=5;axis_ypos<=5;end
						default:begin spiout1<=8'h2D;spiout2<=8'h2D;
											psstatus <= psstatus + 1;end
					endcase
				end
				1 : begin
					case (joy_rx[1])
						8'b1111_1110:begin spiout1=8'h4c;spiout2=8'h32;
											axis_xpos<=6;axis_ypos<=6;end
						8'b1111_1101:begin spiout1=8'h52;spiout2=8'h32;
											axis_xpos<=7;axis_ypos<=7;end
						8'b1111_1011:begin spiout1=8'h4c;spiout2=8'h31;
											axis_xpos<=8;axis_ypos<=8;end
						8'b1111_0111:begin spiout1=8'h52;spiout2=8'h31;
											axis_xpos<=9;axis_ypos<=9;end
						8'b1110_1111:begin spiout1=8'h54;spiout2=8'h49;direct<=2'b00;end
						8'b1101_1111:begin spiout1=8'h43;spiout2=8'h49;direct<=2'b01;end
						8'b1011_1111:begin spiout1=8'h58;spiout2=8'h58;direct<=2'b10;end
						8'b0111_1111:begin spiout1=8'h53;spiout2=8'h51;direct<=2'b11;end
						default:begin spiout1<=8'h2D;spiout2<=8'h2D;psstatus <= 0;end
					endcase
				end
		endcase
	end
    
end
always @(posedge clk or negedge rst) begin
    if( !rst ) begin
        wdata  <= 0;
        wvalid <= 0;
		status <= 0;
    end
	else begin
			case (status)
				0 : begin
					wdata  <= spiout1;
					wvalid <= 1;
					status <= status + 1;
				end
				1 : begin
					if(woready) begin
						wvalid <= 0;
						status <= status + 1;
					end
				end
				2 : begin
					wdata  <= spiout2;
					wvalid <= 1;
					status <= status + 1;
				end
				3 : begin
					if(woready) begin
						wvalid <= 0;
						status <= 0;
					end
				end
			endcase
    end
end

//always @(posedge clk or negedge rst) begin
//    if( !rst ) begin
//		axis_xpos<=10;
//		axis_ypos<=7;
//    end
//	else begin
//		if(axis_xpos>=17||axis_xpos<=2||axis_ypos>=12||axis_ypos<=2)begin
//			axis_xpos<=10;axis_ypos<=7;
//		end
//		else begin
//			case(xypos)
//				2'b00:begin axis_ypos<=axis_ypos-1; end
//				2'b01:begin axis_xpos<=axis_xpos+1; end
//				2'b10:begin axis_ypos<=axis_ypos+1; end
//				2'b11:begin axis_xpos<=axis_xpos-1; end
//			endcase
//		end
//    end
//end
endmodule
